

import java.io.*;
import java.util.*;


public class HomeWork3 {

    private static Map<String, List<ItemToUser>> itemToUser;

    private static Map<String, List<UserToItem>> userToItem;

    private static List userList;

    private static List movieList;

    private static int wirteCount = 0;

    public void readFile(String file_path) throws IOException {
        itemToUser = new HashMap<>();
        userToItem = new HashMap<>();

        File file;
        FileReader fr;
        BufferedReader br;
        file = new File(file_path);
        if (!file.exists()) {
            System.out.println("\"" + file_path + "\" does not exsit!");
            return;
        }
        fr = new FileReader(file);
        br = new BufferedReader(fr);
        String lineText;
        while (br.ready()) {
            lineText = br.readLine();
            lineText = new String(lineText.getBytes(), "UTF-8");
            //System.out.println(lineText);

            //分解数据，将数据存进对应map中
            String[] info = lineText.split("::");
            //为item_to_user赋值 判断有无该电影作为键值
            if (itemToUser.containsKey(info[1])) {
                //取得原先的值，追加数据
                List<ItemToUser> list = itemToUser.get(info[1]);
                ItemToUser item = new ItemToUser();
                item.setUserId(info[0]);
                item.setRating(info[2]);
                list.add(item);
                itemToUser.put(info[1], list);
            } else {
                List<ItemToUser> list = new ArrayList<>();
                ItemToUser item = new ItemToUser();
                item.setUserId(info[0]);
                item.setRating(info[2]);
                list.add(item);
                itemToUser.put(info[1], list);
            }

            //为user_to_item赋值 判断有无该用户作为键值
            if (userToItem.containsKey(info[0])) {
                //取得原先的值，追加数据
                List<UserToItem> list = userToItem.get(info[0]);
                UserToItem item = new UserToItem();
                item.setMovieId(info[1]);
                item.setRating(info[2]);
                list.add(item);
                userToItem.put(info[0], list);
            } else {
                List<UserToItem> list = new ArrayList<>();
                UserToItem item = new UserToItem();
                item.setMovieId(info[1]);
                item.setRating(info[2]);
                list.add(item);
                userToItem.put(info[0], list);
            }
        }

        writeFile();

        br.close();
    }

    public void writeFile() throws IOException {
        FileWriter fw, fw1;
        PrintWriter pw, pw1;
//C://Users/13353/Desktop/movies.dat
        File file = new File("C://Users/13353/Desktop/user_to_item.txt");
        File file1 = new File("C://Users/13353/Desktop/item_to_user.txt");
        if (!file.exists()) {
            file.createNewFile();
        }
        if (!file1.exists()) {
            file1.createNewFile();
        }
        fw = new FileWriter(file);
        pw = new PrintWriter(fw);
        fw1 = new FileWriter(file1);
        pw1 = new PrintWriter(fw1);

        Iterator<Map.Entry<String, List<UserToItem>>> entries = userToItem.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry<String, List<UserToItem>> entry = entries.next();
            pw.println(entry.getKey() + " : " + entry.getValue().toString());
        }

        pw.close();

        Iterator<Map.Entry<String, List<ItemToUser>>> entries1 = itemToUser.entrySet().iterator();
        while (entries1.hasNext()) {
            Map.Entry<String, List<ItemToUser>> entry = entries1.next();
            pw1.println(entry.getKey() + " : " + entry.getValue().toString());
        }

        pw1.close();
    }

    public static void writeSimTable(String info) {
        FileOutputStream o = null;
        String path = "C://Users/13353/Desktop/sim_table.txt";
        byte[] buff = new byte[]{};
        try {
            File file = new File(path);
            if (wirteCount==0){
                file.delete();
            }
            wirteCount++;
            if (!file.exists()) {
                file.createNewFile();
            }
            buff = info.getBytes();
            o = new FileOutputStream(file, true);
            o.write(buff);
            o.flush();
            o.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static float sim(ArrayList va, ArrayList vb) {
        // 如果向量维度不相等，则不能计算，函数退出
        if (va.size() != vb.size()) {
            return 0;
        }

        int size = va.size();
        float simVal = 0;

        float num = 0;// numerator分子
        float den = 1;// denominator分母

        float vaSum = 0; //va的平方和
        float vbSum = 0; //vb的平法和

        for (int i = 0; i < size; i++) {
            num += (float) va.get(i) * (float) vb.get(i); //计算分子
            vaSum += Math.pow((float) va.get(i), 2);  //计算va平方和
            vbSum += Math.pow((float) vb.get(i), 2);  //计算vb平方和
        }
        //计算分母
        den = (float) Math.sqrt(vaSum) * (float) Math.sqrt(vbSum);
        simVal = num / den;
        return simVal;
    }

    public static void main(String[] args) throws IOException {
        HomeWork3 homeWork = new HomeWork3();
        homeWork.readFile("C://Users/13353/Desktop/ratings_train_test.txt");

        //遍历序号前1000电影
        for (int k = 1; k <= 1000; k++) {
            userList = new ArrayList();
            movieList = new ArrayList();

            //得到該电影编号下的用户id
            Iterator<Map.Entry<String, List<ItemToUser>>> entries1 = itemToUser.entrySet().iterator();
            while (entries1.hasNext()) {
                Map.Entry<String, List<ItemToUser>> entry = entries1.next();
                if (entry.getKey().equals(String.valueOf(k))) {
                    for (int j = 0; j < entry.getValue().size(); j++) {
                        userList.add(entry.getValue().get(j).getUserId());
                    }
                }
            }


            //得到該电影编号下用户评论的电影
            for (int i = 0; i < userList.size(); i++) {
                Iterator<Map.Entry<String, List<UserToItem>>> entries = userToItem.entrySet().iterator();
                while (entries.hasNext()) {
                    Map.Entry<String, List<UserToItem>> entry = entries.next();
                    if (entry.getKey().equals(userList.get(i))) {
                        for (int j = 0; j < entry.getValue().size(); j++) {
                            if (!entry.getValue().get(j).getMovieId().equals(String.valueOf(k))) {
                                movieList.add(entry.getValue().get(j).getMovieId());
                            }
                        }
                    }
                }
            }


            //计算相似度

            //首先判断该影片是否在item_to_user中存在
            if (itemToUser.containsKey(String.valueOf(k))){
                String simValue = k+":";
                List<ItemToUser> itemi = itemToUser.get(String.valueOf(k));

                for (int i = 0; i < movieList.size(); i++) {

                    ArrayList vi = new ArrayList();
                    //得到Vi
                    for (ItemToUser item : itemi) {
                        vi.add(Float.parseFloat(item.getRating()));
                    }

                    List<ItemToUser> itemj = itemToUser.get(movieList.get(i));
                    ArrayList vj = new ArrayList();
                    //得到Vj
                    for (ItemToUser item : itemj) {
                        vj.add(Float.parseFloat(item.getRating()));
                    }

                    //比较两个数组的维度
                    if (vi.size() > vj.size()) {
                        for (int j = 0; j < vj.size() - vi.size(); j++) {
                            vi.add(0);
                        }
                    } else {
                        for (int j = 0; j < vi.size() - vj.size(); j++) {
                            vj.add(0);
                        }
                    }

                    //相似度
                    float simVal = sim(vi, vj);
                    simValue += movieList.get(i) + "," + simVal + "\t";
                }
                simValue+="\r\n";
                //存儲sim_table中
                writeSimTable(simValue);
            }

        }
        System.out.println("用户id获取完成");
        System.out.println("获取用户评论完成");
        System.out.println("相似度分析完成");
    }
}
